package web.jdbc;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import web.clazz.Clazz;
import web.jdbc.function.Delete;
import web.jdbc.function.Insert;
import web.jdbc.function.Select;
import web.jdbc.function.Update;
import web.util.Log;

/** 实现{@link IQuerySQL}&lt;T&gt;接口，用于数据库操作，主要方法如下：
 * <pre>
 * 
 * {@link #getResultList()}		返回List&lt;Object[]&gt;
 * {@link #getResultList(Class)}	返回List&lt;T&gt;
 * </pre>
 * 
 * @author 乐渊
 * @version 1.0
 * @see Delete
 * @see Insert
 * @see Select
 * @see Update
 * */
public class QuerySQL<T> implements IQuerySQL<T> {
	public ResultSet rs = null;
	private Connection conn = null;
	private Statement st = null;
	private Log log = new Log();
	
	private Statement getST() throws SQLException {
		if (st == null) {
			if (conn == null) {
				conn = DBPool.getConnection();
				st = conn.createStatement();
			} else{
				st = conn.createStatement();
			}
		}
		return st;
	}

	private Connection getConn(){
		if(conn == null)
			conn = DBPool.getConnection();
		return conn;
	}
	
	@Override
	public IQuerySQL<T> executeSQL(String sql) {
		try {
			rs = getST().executeQuery(sql);
		} catch (SQLException e) {
			log.setLog("执行SQL：[" + sql + "] 时出错， 请检查！");
		}
		return this;
	}

	@Override
	public List<Object[]> getResultList() {

		List<Object[]> list = new ArrayList<>();
		try {
			ResultSetMetaData rsmd = rs.getMetaData();
			// 获取列数
			int columnCount = rsmd.getColumnCount();
			while (rs.next()) {
				Object[] object = new Object[columnCount];
				for (int i = 1; i <= columnCount; i++)
					object[i - 1] = rs.getObject(i);
				list.add(object);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			this.close();
		}
		return list;
	}

	@Override
	public List<T> getResultList(Class<?> clazz) {

		List<T> list = new ArrayList<>();
		Map<Field, Method> map = FieldsGetSet.getFieldGetOrSet(clazz, "set");
		DataOperator<T> dor = new DataOperator<>();

		try {
			if (rs != null) {
				while (rs.next()) {
					@SuppressWarnings("unchecked")
					T t = (T) clazz.newInstance();
					Clazz cla = GETClazz.getClazz(t);
					if(cla == null)
						return null;
					Object obj = null;
					for (Field key : map.keySet()) {//不是所有的成员名都是列名
						if(cla.getFields().containsKey(key)){
							obj = cla.getFields().get(key);
						}else{
							obj = key;
						}
						Object param = dor.getData(obj, rs);// 提取查询结果
						map.get(key).invoke(t, new Object[] { param });// 调用set方法保存结果
					}
					list.add(t);
				}
			}
		} catch (SQLException | InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			log.setLog("执行方法  [getResultList(Class<?> clazz)] 时出错！");
		} finally {
			this.close();
		}

		return list;
	}

	@Override
	public T getSingleResult(Class<?> clazz) {
		List<T> list = getResultList(clazz);
		if (list.size() > 0 && list.size() < 2) {
			return list.get(0);
		} else {
			log.setLog("查询结果数量不等于1！");
			return null;
		}

	}

	@Override
	public Object[] getSingleResult() {
		List<Object[]> list = getResultList();
		if (list.size() > 0 && list.size() < 2)
			return list.get(0);
		else {
			log.setLog("查询结果数量不等于1！");
			return null;
		}
	}

	@Override
	public boolean insertData(T t) {
		boolean b = false;
		try {
			b = new Insert<T>(getConn(), t, GETClazz.getClazz(t)).getRS();
		} catch (SQLException e1) {
			log.setLog("添加：" + t + " 时出错， 请检查！");
		}finally{
			this.close();
		}
		return b;
	}

	@Override
	public void deleteData(T t) {
		try {
			new Delete<T>(getConn(), t, GETClazz.getClazz(t)).getRS();
		} catch (SQLException e) {
			log.setLog("删除：" + t + " 时出错， 请检查！");
		}finally{
			this.close();
		}

	}

	@Override
	public T updateData(final T t) {

		try {
			new Update<T>(getConn(), t, GETClazz.getClazz(t)).getRS();
			log.setLog("数据更新成功！");
		} catch (SQLException e) {
			log.setLog("数据更新失败！");
		}

		return selectData(t);
	}

	@Override
	public T selectData(T t) {

		try {
			rs = new Select<T>(getConn(), t, GETClazz.getClazz(t)).getRS();
		} catch (SQLException e) {
			log.setLog("查找：" + t + " 时出错， 请检查！");
		}
		t = getSingleResult(t.getClass());

		return t;
	}

	/**关闭ResultSet Statment 释放Connection到连接池
	 * */
	private void close() {
		try {
			if (rs != null)
				rs.close();
			if (st != null)
				st.close();
			if (conn != null) {
				DBPool.releaseConnection(conn);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			rs = null;
			st = null;
			conn = null;
		}
	}
}
